#include "hardcodedRunAnimation.h"

#include <spri/data.h>
#include <spri/assets.h>

#include <util/indexMap.h>

#include <foun/foun_math.h>
#include <foun/debug.h>

#include <string.h>

/*
 * Internal Constants
 */
static const f32 FRAME_DURATION = 60.0f;

static const f32 HIP_THRUST_ANGLE = lct::foun::RotationsFromDegrees(90.0f);
static const f32 HIP_PLANT_ANGLE = lct::foun::RotationsFromDegrees(0.0f);
static const f32 HIP_RELEASE_ANGLE = lct::foun::RotationsFromDegrees(-45.0f);
static const f32 HIP_RETURN_ANGLE = lct::foun::RotationsFromDegrees(45.0f);

static const f32 KNEE_THRUST_ANGLE = lct::foun::RotationsFromDegrees(-90.0f);
static const f32 KNEE_PLANT_ANGLE = lct::foun::RotationsFromDegrees(-45.0f);
static const f32 KNEE_RELEASE_ANGLE = lct::foun::RotationsFromDegrees(0.0f);
static const f32 KNEE_RETURN_ANGLE = lct::foun::RotationsFromDegrees(-135.0f);

static const f32 SHOULDER_THRUST_ANGLE = lct::foun::RotationsFromDegrees(90.0f);
static const f32 SHOULDER_PLANT_ANGLE = lct::foun::RotationsFromDegrees(0.0f);
static const f32 SHOULDER_RELEASE_ANGLE = lct::foun::RotationsFromDegrees(-45.0f);
static const f32 SHOULDER_RETURN_ANGLE = lct::foun::RotationsFromDegrees(0.0f);

static const f32 ELBOW_THRUST_ANGLE = lct::foun::RotationsFromDegrees(90.0f);
static const f32 ELBOW_PLANT_ANGLE = lct::foun::RotationsFromDegrees(0.0f);
static const f32 ELBOW_RELEASE_ANGLE = lct::foun::RotationsFromDegrees(45.0f);
static const f32 ELBOW_RETURN_ANGLE = lct::foun::RotationsFromDegrees(90.0f);

static const f32 WAIST_LEAN_ANGLE = lct::foun::RotationsFromDegrees(-15.0f);
static const f32 WAIST_STRAIGHT_ANGLE = lct::foun::RotationsFromDegrees(0.0f);

/*
 * Public Static
 */
lct::spri::AnimationAsset* HardcodedRunAnimation::BuildAsset(lct::foun::Allocator* pAllocator)
{
	static const u32 TRACK_COUNT = 9;

	lct::spri::TrackData* pTrackDataArray = pAllocator->AllocTypeArray<lct::spri::TrackData>(TRACK_COUNT);
	lct::spri::KeyData** pKeyDataArrayArray = pAllocator->AllocTypeArray<lct::spri::KeyData*>(TRACK_COUNT);
	{
		u32 trackIndex = 0;
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_THRUST_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "hip_r");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_THRUST_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "knee_r");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = HIP_RELEASE_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "hip_l");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = KNEE_RELEASE_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "knee_l");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_RELEASE_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "shoulder_r");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_RELEASE_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "elbow_r");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = SHOULDER_THRUST_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "shoulder_l");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_THRUST_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_PLANT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_RELEASE_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_RETURN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = ELBOW_THRUST_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "elbow_l");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		{
			static const u32 KEY_COUNT = 5;

			lct::spri::KeyData* pKeyDataArray = pAllocator->AllocTypeArray<lct::spri::KeyData>(KEY_COUNT);
			u32 keyIndex = 0;
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = WAIST_LEAN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = WAIST_STRAIGHT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = WAIST_LEAN_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = WAIST_STRAIGHT_ANGLE;
				pKeyData->slope = 0.0f; // fixup
				pKeyData->curveType = lct::spri::CURVE_TYPE_LINEAR;
			}
			{
				lct::spri::KeyData* pKeyData = pKeyDataArray + keyIndex++;
				pKeyData->frame = FRAME_DURATION / (KEY_COUNT - 1) * (keyIndex - 1);
				pKeyData->value = WAIST_LEAN_ANGLE;
				pKeyData->slope = 0.0f;
				pKeyData->curveType = lct::spri::CURVE_TYPE_FLAT;
			}
			LCT_ASSERT(keyIndex == KEY_COUNT);

			lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
			strcpy(pTrackData->targetName, "waist");
			pTrackData->targetType = lct::spri::TARGET_TYPE_JOINT;
			pTrackData->targetPropertyType = lct::spri::JOINT_PROPERTY_TYPE_ROTATE;
			pTrackData->finishType = lct::spri::FINISH_TYPE_LOOP;
			pTrackData->keyCount = KEY_COUNT;

			pKeyDataArrayArray[trackIndex] = pKeyDataArray;

			++trackIndex;
		}
		LCT_ASSERT(trackIndex == TRACK_COUNT);
	}

	lct::spri::AnimationAsset::Track* pTrackArray = pAllocator->AllocTypeArray<lct::spri::AnimationAsset::Track>(TRACK_COUNT);
	for (u32 trackIndex = 0; trackIndex < TRACK_COUNT; ++trackIndex) {
		lct::spri::AnimationAsset::Track* pTrack = pTrackArray + trackIndex;
		lct::spri::TrackData* pTrackData = pTrackDataArray + trackIndex;
		lct::spri::KeyData* pKeyDataArray = pKeyDataArrayArray[trackIndex];
		pTrack->pTrackData = pTrackData;
		pTrack->pKeyDataArray = pKeyDataArray;
	}

	lct::spri::AnimationData* pAnimationData = pAllocator->AllocType<lct::spri::AnimationData>();
	strcpy(pAnimationData->name, "run");
	pAnimationData->trackCount = TRACK_COUNT;

	lct::spri::AnimationAsset* pAnimationAsset = pAllocator->AllocType<lct::spri::AnimationAsset>();
	pAnimationAsset->pAnimationData = pAnimationData;
	pAnimationAsset->pTrackArray = pTrackArray;

	return pAnimationAsset;
}
